package com.jingdianjichi.subject.domain.util;

import com.alibaba.fastjson.JSON;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * 一个通用的缓存工具类，支持通过缓存键获取单个对象或对象列表，并能够在缓存未命中时，通过提供的函数动态加载数据。
 *
 * @param <K> 缓存键的类型
 * @param <V> 缓存值的类型
 */
@Component // 表明这是一个Spring组件，Spring会在启动时实例化并管理它
public class CacheUtil<K,V> {

	// 注入一个本地缓存实例，这里假设已经在配置类中定义了这个bean
	@Resource
	private Cache<String,String> localCache;

	/**
	 * 尝试从缓存中获取一个对象列表。如果缓存中有数据，则直接返回数据；如果没有，则调用提供的函数加载数据，然后将结果存入缓存。
	 *
	 * @param cacheKey 缓存键，用于在缓存中定位数据
	 * @param clazz 对象列表中对象的类型
	 * @param function 如果缓存中没有数据，将调用这个函数来加载数据。函数接受缓存键作为输入，返回数据列表。
	 * @return 缓存或加载的数据列表
	 */
	public List<V> getResult(String cacheKey, Class<V> clazz,
							 Function<String,List<V>> function) {
		List<V> resultList = new ArrayList<>();
		// 尝试从缓存中获取数据
		String content = localCache.getIfPresent(cacheKey);
		if(StringUtils.isNotBlank(content)) {
			// 如果缓存中有数据，将其从JSON字符串反序列化为对象列表
			resultList = JSON.parseArray(content,clazz);
		}else {
			// 如果缓存中没有数据，调用提供的函数加载数据
			resultList = function.apply(cacheKey);
			if(!CollectionUtils.isEmpty(resultList)) {
				// 如果加载的数据不为空，将其序列化为JSON字符串并存入缓存
				localCache.put(cacheKey,JSON.toJSONString(resultList));
			}
		}
		return resultList;
	}

	/**
	 * 这个方法的实现暂未完成，目前只返回一个空的HashMap。
	 *
	 * @param cacheKey 缓存键
	 * @param clazz 值的类型
	 * @param function 加载数据的函数
	 * @return 缓存或加载的数据Map
	 */
	public Map<K, V> getMapResult(String cacheKey, Class<V> clazz,
								  Function<String, Map<K, V>> function) {
		return new HashMap<>();
	}

}

